﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace SimpleExpression
{
    public class SelectVisitor : ExpressionVisitor
    {
        protected ISelectCommandStrategy strategy;

        public SelectVisitor(ISelectCommandStrategy strategy)
        {
            this.strategy = strategy;    
        }
		
        public override void Visit(EntityExpression expression)
        {
            // Add distinct
            this.strategy.AddDistinctClause(expression);

            // Add column set
            expression.ColumnSetExpression.Accept(this);

            // Add from 
            this.strategy.AddFromClause(expression);

            // Add link entity
            expression.JoinEntityExpression.Accept(this);

            // Add criteria
            expression.FilterExpression.Accept(this);

            // Add groupby
            expression.GroupByExpression.Accept(this);

            // Add order
            expression.OrderExpression.Accept(this);

            // Add paging
            expression.PagingExpression.Accept(this);

            this.strategy.WriteCommand();
        }

        public override void Visit(ColumnSetExpression expression)
        {
            foreach (AttributeExpression attributeExpression in expression.Attributes)
            {
                attributeExpression.Accept(this);
            }
        }

        public override void Visit(AttributeExpression expression)
        {
            this.strategy.AddAttribute(expression);
        }

        public override void Visit(JoinEntityExpression expression)
        {
            foreach (LinkEntityExpression linkEntityExpression in expression.LinkedEntities)
            {
                linkEntityExpression.Accept(this);
            }
        }

        public override void Visit(LinkEntityExpression expression)
        {
            expression.FilterExpression.Accept(this);
            
            this.strategy.AddLinkEntity(expression);
        }

        public override void Visit(FilterExpression expression)
        {
            if (expression.Conditions.Count > 0)
            {
                this.strategy.BeginFilterExpression(expression);

                foreach (Expression condition in expression.Conditions)
                {
                    condition.Accept(this);
                }

                this.strategy.EndFilterExpression(expression);
            }
        }

        public override void Visit(ConditionExpression expression)
        {
            this.strategy.AddCondition(expression);
        }

        public override void Visit(GroupByExpression expression)
        {
            this.strategy.AddGroupByClause(expression);
        }

        public override void Visit(OrderExpression expression)
        {
            this.strategy.AddOrderClause(expression);
        }

        public override void Visit(PagingExpression expression)
        {
            this.strategy.AddPagingClause(expression);
        }

    }
}
